package com.roadjava.rbac.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.roadjava.rbac.bean.entity.LinkRoleAuthorityDO;
import com.roadjava.rbac.bean.entity.RoleDO;
import com.roadjava.rbac.bean.req.role.AssignAuthorityReq;
import com.roadjava.rbac.bean.req.role.RoleAddReq;
import com.roadjava.rbac.bean.req.role.RolePageReq;
import com.roadjava.rbac.bean.req.role.RoleUpdateReq;
import com.roadjava.rbac.bean.res.Result;
import com.roadjava.rbac.bean.vo.RoleVO;
import com.roadjava.rbac.mapper.RoleMapper;
import com.roadjava.rbac.service.LinkRoleAuthorityService;
import com.roadjava.rbac.service.LinkUserRoleService;
import com.roadjava.rbac.service.RoleService;
import com.roadjava.rbac.util.ConvertUtil;
import com.roadjava.rbac.util.PageUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 针对表【role(角色表)】的数据库操作Service实现
 *
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, RoleDO>
        implements RoleService{
    @Resource
    private LinkUserRoleService linkUserRoleService;
    @Resource
    private LinkRoleAuthorityService linkRoleAuthorityService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(RoleAddReq addReq) {
        RoleDO entity = ConvertUtil.convert(addReq, RoleDO.class);
        save(entity);
    }

    //这个是分页查询
    @Override
    public Result<List<RoleVO>> queryPage(RolePageReq pageReq) {
        IPage<RoleDO> page = PageUtil.buildPage(pageReq);
        LambdaQueryWrapper<RoleDO> lqw = Wrappers.<RoleDO>lambdaQuery()
                .like(StrUtil.isNotBlank(pageReq.getRoleCnName()),RoleDO::getRoleCnName,pageReq.getRoleCnName())
                .orderByDesc(RoleDO::getId);
        IPage<RoleDO> resultPage = page(page, lqw);
        return ConvertUtil.convert(resultPage,RoleVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Long id) {
        try {
            // 删除用户角色的关联信息
            linkUserRoleService.deleteByRoleId(id);
        } catch (Exception e) {
            throw new IllegalStateException("删除用户角色关联信息时出错: " + e.getMessage(), e);
        }

        try {
            // 删除角色和权限的关联关系
            linkRoleAuthorityService.deleteByRoleId(id);
        } catch (Exception e) {
            throw new IllegalStateException("删除角色和权限关联信息时出错: " + e.getMessage(), e);
        }

        try {
            // 删除角色
            removeById(id);
        } catch (Exception e) {
            throw new IllegalStateException("删除角色时出错: " + e.getMessage(), e);
        }

    }


    @Override
    public RoleVO queryById(Long id) {
        RoleDO entity = getById(id);
        RoleVO vo = ConvertUtil.convert(entity, RoleVO.class);
        List<Long> authorityIds = linkRoleAuthorityService.listAuthorityIdByRoleId(id);
        vo.setAuthorityIds(authorityIds);
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modifyById(RoleUpdateReq updateReq) {
        RoleDO entityToUpdate = ConvertUtil.convert(updateReq, RoleDO.class);
        updateById(entityToUpdate);
    }

    @Override
    public List<RoleVO> queryAll() {
        LambdaQueryWrapper<RoleDO> lqw = Wrappers.<RoleDO>lambdaQuery()
                .orderByDesc(RoleDO::getId);
        List<RoleDO> list = list(lqw);
        return ConvertUtil.convert(list,RoleVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assignAuthority(AssignAuthorityReq assignAuthorityReq) {
        // 删除角色和权限的关联关系
        linkRoleAuthorityService.deleteByRoleId(assignAuthorityReq.getRoleId());
        // 保存关联关系
        List<LinkRoleAuthorityDO> list = assignAuthorityReq.getAuthorityIds().stream()
                .map(authorityId -> {
                    LinkRoleAuthorityDO entity = ConvertUtil.convert(assignAuthorityReq, LinkRoleAuthorityDO.class);
                    entity.setAuthorityId(authorityId);
                    return entity;
                }).collect(Collectors.toList());
        linkRoleAuthorityService.saveBatch(list);
    }
}